#include "NameDB.h"
#include <stdexcept>
#include <fstream>
#include <iostream>

using namespace std;
NameDB::NameDB(string_view nameFile)
{
	ifstream inputFile(nameFile.data());
	if (!inputFile) {
		throw invalid_argument("Unable to open file");
	}

	string name;
	while (inputFile >> name) {
    auto item = mNames.find(name);
    if (item != mNames.end()) {
      item->second++;
    } else {
      mNames[name] = 1;
      item = mNames.find(name);
      mVector.push_back(&(*item));
    }
	}

  sort(mVector.begin(), mVector.end(), [](auto x, auto y) {
    return x->second < y->second;
  });
}

int NameDB::getNameRank(string_view name) const
{
	int num = getAbsoluteNumber(name);

	if (num == -1) {
		return -1;
	}

/*
  int lo = 0, hi = mVector.size();
  int mi = 0;
  while (lo < hi) {
    mi = (lo + hi) >> 1;
    if (mVector[mi]->second > num) {
      hi = mi;
    } else if (mVector[mi]->second < num) {
      lo = mi + 1;
    } else {
      break;
    }
  }
  return mVector.size() - mi;
  */

  auto low_bound = lower_bound(mVector.begin(), mVector.end(), num, [](auto x, int val){
    return x->second < val; 
  });

  return mVector.end() - low_bound;

}

int NameDB::getAbsoluteNumber(string_view name) const
{
	auto res = mNames.find(name.data());
	if (res != end(mNames)) {
		return res->second;
	}

	return -1;
}